import { Injectable, OnModuleInit } from '@nestjs/common';
import * as md5 from 'md5';
import { LantUtil } from '../../../utils/lant.util';
import { Guard, GuardDisplay } from '../../guard/constants/guard.constant';
import { GuardService } from '../../guard/services/guard.service';
import { LogAppender } from '../../log/constants/log.constant';
import { LogService } from '../../log/services/log.service';
import { OrganizationService } from '../../organization/services/organization.service';
import { OrganizationType, RoleType, Role, UserType } from '../../role/constants/role.constant';
import { RoleService } from '../../role/services/role.service';
import { UserService } from '../../user/services/user.service';

@Injectable()
export class InitService implements OnModuleInit {
  constructor(
    private readonly organizationService: OrganizationService,
    private readonly userService: UserService,
    private readonly roleService: RoleService,
    private readonly guardService: GuardService,
    private readonly logService: LogService,
    private readonly lantUtil: LantUtil
  ) {}

  async onModuleInit() {
    this.logService.info(LogAppender.init, '系统启动检测中……');
    await this.checkGuard();
    await this.checkAdminRole();
    await this.checkManagerRole();
    await this.checkViewerRole();
    await this.checkAdminOrganization();
    await this.checkAdminUser();
  }

  /** 初始化权限表 */
  private async checkGuard() {
    for (const name of Object.values(Guard)) {
      try {
        const guard = await this.guardService.findOneByName(name);
        if (guard) await this.guardService.update(guard.uuid, name, GuardDisplay[name]);
        else await this.guardService.create(name, GuardDisplay[name]);
        this.logService.info(LogAppender.init, `权限:${name}检查成功`);
      } catch (error) {
        this.logService.error(LogAppender.init, '权限初始化失败', this.lantUtil.parseError(error));
      }
    }
  }

  /** 初始化系统管理员角色 */
  private async checkAdminRole() {
    const [adminRole, guardList] = await Promise.all([await this.roleService.findOneByName(Role.admin), await this.guardService.find()]);

    try {
      if (!adminRole)
        return await this.roleService.create(
          Role.admin,
          guardList.map(guard => guard.uuid),
          '系统管理员',
          RoleType.system
        );
      if (adminRole.guardUuidList.length !== guardList.length) {
        return await this.roleService.update(
          adminRole.uuid,
          adminRole.name,
          adminRole.description,
          guardList.map(guard => guard.uuid)
        );
      }
      this.logService.info(LogAppender.init, '管理员角色初始化成功');
    } catch (error) {
      this.logService.error(LogAppender.init, '管理员角色初始化失败', this.lantUtil.parseError(error));
    }
  }

  /**
   * 初始化管理员权限
   */
  private async checkManagerRole() {
    try {
      const userRole = await this.roleService.findOneByName(Role.manager);
      if (!userRole) {
        const guardList = await this.guardService.findAllByNameList([Guard.AreaManage, Guard.AreaView]);
        const guardUuidList = guardList.map(guard => guard.uuid);
        return await this.roleService.create(Role.manager, guardUuidList, '区域管理员', RoleType.system);
      }
      this.logService.info(LogAppender.init, '区域管理员角色初始化成功');
    } catch (error) {
      this.logService.error(LogAppender.init, '区域管理员角色初始化失败', this.lantUtil.parseError(error));
    }
  }

  /**
   * 初始化查看员角色
   */
  private async checkViewerRole() {
    try {
      const userRole = await this.roleService.findOneByName(Role.viewer);
      if (!userRole) {
        const guardList = await this.guardService.findAllByNameList([Guard.AreaView]);
        const guardUuidList = guardList.map(guard => guard.uuid);
        return await this.roleService.create(Role.viewer, guardUuidList, '区域查看员', RoleType.system);
      }
      this.logService.info(LogAppender.init, '区域查看员角色初始化成功');
    } catch (error) {
      this.logService.error(LogAppender.init, '区域查看员角色初始化失败', this.lantUtil.parseError(error));
    }
  }

  /**
   * 检查系统默认组织
   */
  private async checkAdminOrganization() {
    try {
      const organizationList = await this.organizationService.findDescendantsByName(OrganizationType.system);
      if (organizationList) return;

      await this.organizationService.create(OrganizationType.system, 1, '系统默认组织');
      this.logService.info(LogAppender.init, '系统默认组织初始化成功');
    } catch (error) {
      this.logService.error(LogAppender.init, '系统默认组织初始化失败', this.lantUtil.parseError(error));
    }
  }

  /** 初始化系统超级管理员 */
  private async checkAdminUser() {
    try {
      const adminRole = await this.roleService.findOneByName(Role.admin);
      const count = await this.userService.findCountByRoleUuid(adminRole.uuid);
      if (count > 0) return;

      const rootOrganization = await this.organizationService.findOneRoot();
      await this.userService.create('root', md5('123qwe'), [adminRole.uuid], [rootOrganization.id], rootOrganization.id, UserType.system);
      this.logService.info(LogAppender.init, '系统超级管理员初始化成功');
    } catch (error) {
      this.logService.error(LogAppender.init, '系统超级管理员初始化失败', this.lantUtil.parseError(error));
    }
  }
}
